package rpc.registry.nacos;

import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.Service;
import lombok.val;
import org.apache.curator.x.discovery.ServiceInstance;
import rpc.common.helper.RpcServiceHelper;
import rpc.constants.RpcConstants;
import rpc.loadbalancer.api.ServiceLoadBalancer;
import rpc.loadbalancer.helper.ServiceLoadBalancerHelper;
import rpc.protocol.meta.ServiceMeta;
import rpc.registry.api.RegistryService;
import rpc.registry.api.config.RegistryConfig;
import rpc.spi.annotation.SPIClass;
import rpc.spi.loader.ExtensionLoader;

import java.util.*;

import java.io.IOException;

@SPIClass
public class NacosRegistryService implements RegistryService {

    Instance instance;
    public  static NamingService namingService;

    private ServiceLoadBalancer<ServiceMeta> serviceEnhancedLoadBalancer;

    //负载均衡接口
    private ServiceLoadBalancer<ServiceInstance<ServiceMeta>> serviceLoadBalancer;

    @Override
    public void init(RegistryConfig registryConfig) throws Exception {

//        String serverAddr= "119.91.35.170:" + 8848;// Nacos 服务ip地址
        String serverAddr=registryConfig.getRegistryAddr();
        String namesPace="public";//命名空间
        // 创建连接 Nacos 服务注册中心的配置
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);// 指定ip 端口
        properties.put(PropertyKeyConst.NAMESPACE, namesPace); // 指定命名空间
        namingService = NamingFactory.createNamingService(properties);
        //增强型负载均衡策略
        if (registryConfig.getRegistryLoadBalanceType().toLowerCase().contains(RpcConstants.SERVICE_ENHANCED_LOAD_BALANCER_PREFIX)){
            this.serviceEnhancedLoadBalancer = ExtensionLoader.getExtension(ServiceLoadBalancer.class, registryConfig.getRegistryLoadBalanceType());
        }else{
            this.serviceLoadBalancer = ExtensionLoader.getExtension(ServiceLoadBalancer.class, registryConfig.getRegistryLoadBalanceType());
        }


    }

    @Override
    public ServiceMeta select(List<ServiceMeta> serviceMetaList, int invokerHashCode, String sourceIp) {
        return null;
    }

    @Override
    public List<ServiceMeta> discoveryAll() throws Exception {
        return null;
    }

    @Override
    public void register(ServiceMeta serviceMeta) throws Exception {
        Instance instance = new Instance();
//        instance.setIp("119.91.35.170");
        instance.setIp(serviceMeta.getServiceAddr());
//        instance.setPort(8848);
        instance.setPort(serviceMeta.getServicePort());
        instance.setEphemeral(false);
        instance.setHealthy(true);
//        instance.setServiceName("rpc");
        instance.setServiceName(serviceMeta.getServiceName());
        Map<String, String> map = new HashMap<String, String>();
        map.put("realIp", "119.91.35.170");
        map.put("info", "瞎搞");
        instance.setMetadata(map);// 元数据
        // 注册服务实例到 Nacos 服务注册中心
        namingService.registerInstance(RpcServiceHelper.buildServiceKey(serviceMeta.getServiceName(), serviceMeta.getServiceVersion(), serviceMeta.getServiceGroup()), instance);

    }

    @Override
    public ServiceMeta discovery(String serviceName, int invokerHashCode, String sourceIp) throws Exception {
        List<Instance> serviceInstances  = namingService.getAllInstances(serviceName);
        System.out.println("=================================================================================");
        System.out.println(serviceInstances);
        System.out.println("=================================================================================");
        return this.serviceEnhancedLoadBalancer.select(ServiceLoadBalancerHelper.getServiceMetaList_Nacos(serviceInstances),invokerHashCode,sourceIp);

    }


    @Override
    public void unRegister(ServiceMeta serviceMeta) throws Exception {
//        String serverAddr= serviceMeta.getServiceAddr();
        final val Port = serviceMeta.getServicePort();
        final val serviceName = serviceMeta.getServiceName();
        final val serviceAddr=serviceMeta.getServiceAddr();
        namingService.deregisterInstance(serviceName,serviceAddr,Port);//服务名、服务的IP、服务的端口
    }


    @Override
    public void destroy() throws IOException {

    }


}
